import requests
import urllib3
from vmware.vapi.vsphere.client import create_vsphere_client
from pyVim.connect import SmartConnectNoSSL
from pyVmomi import vim
import time
# session = requests.session()
# session.verify = False
# urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# client = create_vsphere_client(server="caxj-vcsa01.catlbattery.com", username='catl-itom-service@catlbattery.com', password='Xiujdr@2019#', session=session)
# client.vcenter.VM.list()
# vm = client.vcenter.VM.list(client.vcenter.VM.FilterSpec(names={'caxjtaaa-catl-nddb14'}))[0]
# print(dir(vm.vm))
# state = client.vcenter.vm.Power.get(vm.vm)
# client.vcenter.vm.Power.stop(vm)
# print(state)
# client.vcenter.vm.get()
# print(client.vcenter.VM.list(client.vcenter.VM.FilterSpec(vms={'vm-70162'})))


class VmManage(object):

    def __init__(self, host, user, password, port, ssl):
        self.config = None
        self.host = host
        self.user = user
        self.pwd = password
        self.port = port
        self.sslContext = ssl
        try:
            self.client = SmartConnectNoSSL(host=host,
                                            user=user,
                                            pwd=password,
                                            port=443
                                            )
            self.content = self.client.RetrieveContent()
            self.result = True
        except Exception as e:
            self.result = e

    def wait_for_task(self, task):
        """ wait for a vCenter task to finish """
        task_done = False

        while not task_done:
            print("task.....%s " % task.info.state)
            time.sleep(2)
            if task.info.state == 'success':
                return {'message': u'执行成功', 'status': True}

            if task.info.state == 'error':
                print("there was an error", f'message:{task.info.error.msg}')

                return {'message': task.info.error.msg, 'status': True}

    def _get_all_objs(self, obj_type, folder=None):
        """
        根据对象类型获取这一类型的所有对象
        """
        if folder is None:
            container = self.content.viewManager.CreateContainerView(self.content.rootFolder, obj_type, True)
        else:
            container = self.content.viewManager.CreateContainerView(folder, obj_type, True)
        return container.view

    def _get_obj(self, obj_type, name):
        """
        根据对象类型和名称来获取具体对象
        """
        obj = None
        content = self.client.RetrieveContent()
        container = content.viewManager.CreateContainerView(content.rootFolder, obj_type, True)
        for c in container.view:
            if c.name == name:
                obj = c
                break
        return obj

    def add_disk(self, vm_obj, capacity):
        spec = vim.vm.ConfigSpec()
        dev_changes = []
        # capacity 为 存储盘容量将单位改为 G
        new_disk_kb = capacity * 1024 * 1024
        unit_number = 0
        # 遍历所有的硬件设备，找合适的位置添加
        for dev in vm_obj.config.hardware.device:
            if hasattr(dev.backing, 'fileName'):
                unit_number = int(dev.unitNumber) + 1
                # unit_number 7 reserved for scsi controller
                if unit_number == 7:
                    unit_number += 1
                if unit_number >= 16:
                    logging.error('we don\'t support this many disks')
            if isinstance(dev, vim.vm.device.VirtualSCSIController):
                controller = dev

        disk_spec = vim.vm.device.VirtualDeviceSpec()
        disk_spec.fileOperation = "create"
        disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
        disk_spec.device = vim.vm.device.VirtualDisk()
        disk_spec.device.backing = vim.vm.device.VirtualDisk.FlatVer2BackingInfo()
        disk_spec.device.backing.thinProvisioned = True
        disk_spec.device.backing.diskMode = 'persistent'

        disk_spec.device.unitNumber = unit_number
        disk_spec.device.capacityInKB = new_disk_kb
        disk_spec.device.controllerKey = controller.key
        dev_changes.append(disk_spec)
        spec.deviceChange = dev_changes
        task = vm_obj.ReconfigVM_Task(spec=spec)
        result1 = self.wait_for_task(task)
        if result1['status']:
            data = {'message': u'硬盘添加成功', 'result': True}
        else:
            data = {'message': u'硬盘添加失败: %s' % result1['message'], 'result': False}
        return data

    def change_vm_cpu_and_memory(self, vm_obj, cpu, memory ):
        cspec = vim.vm.ConfigSpec()
        cspec.numCPUs = cpu
        # 将 4 核心分配在两个插槽，一个插槽两核心
        # cspec.numCoresPerSocket = int(cspec.numCPUs / 2)
        # 8G
        cspec.memoryMB = 1024 * memory
        # 启动 cpu 热添加
        cspec.cpuHotAddEnabled = True
        # 启动内存在线扩缩
        cspec.memoryHotAddEnabled = True
        task = vm_obj.Reconfigure(cspec)
        result1 = self.wait_for_task(task)
        if result1['status']:
            data = {'message': u'cpu 和 内存变更成功', 'result': True}
        else:
            data = {'message': u'cpu 和 内存变更添加失败: %s' % result1['message'], 'result': False}
        return data

    def get_vm_ip(self, vm_obj ):
        """ 获取 VM 所有 IP 地址 """
        ips = []
        for i in vm_obj.guest.net:
            if i.network:
                for b in range(6):
                    if i.ipAddress:
                        ips.extend(i.ipAddress)
                        return ips
                    else:
                        print("VM 没有获取到IP地址等待10秒")
                        time.sleep(10)
            else:
                print('VM 未配置网卡')
        print('VM 未获取到IP地址,请检测网络状态或者 DHCP 服务器')
        return ips

    def change_vm_name(self,vm_obj,newname):
        cspec = vim.vm.ConfigSpec()
        cspec.name = newname
        task = vm_obj.Reconfigure(cspec)
        result1 = self.wait_for_task(task)
        return result1
    def change_vm_status(self,vm_obj):
        if vm_obj.runtime.powerState == vim.VirtualMachinePowerState.poweredOn:
            task = vm_obj.PowerOff()
            result1 = self.wait_for_task(task)
            return result1
        else:
            print("vm 属于关机状态")
            return True
if __name__ == "__main__":
    ip = "caxj-vcsa01.catlbattery.com"
    user = "catl-itom-service@catlbattery.com"
    password = "Xiujdr@2019#"
    port = 443
    vm_name = "caxjtaaa-catl-nddb1410.154.197.39"
    vm_ip = "10.154.197.39"
    vm = VmManage(host=ip,user=user,password=password,port=port,ssl=None)
    vm_obj = vm._get_obj([vim.VirtualMachine], vm_name)
    vm_obj_ip = vm.get_vm_ip(vm_obj)
    if vm_ip in vm_obj_ip:
        new_vm_name = "awp_" + vm_name + "_" + vm_ip
        res = vm.change_vm_name(vm_obj,new_vm_name)
        status_result = vm.change_vm_status(vm_obj)
        print(vm_obj_ip,vm_obj,res,status_result)
    else:
        print("虚拟机ip与name信息不一致")